package com.ev.hr.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.ev.apis.model.DsResultResponse;
import com.ev.custom.domain.ContentAssocDO;
import com.ev.custom.service.ContentAssocService;
import com.ev.custom.service.NoticeService;
import com.ev.framework.config.ConstantForHr;
import com.ev.framework.il8n.MessageSourceHandler;
import com.ev.framework.utils.*;
import com.ev.hr.dao.CandidateInfoDao;
import com.ev.hr.dao.InterviewRecordDao;
import com.ev.hr.dao.InterviewRecordDetailDao;
import com.ev.hr.domain.CandidateInfoDO;
import com.ev.hr.domain.InterviewRecordDO;
import com.ev.hr.domain.InterviewRecordDetailDO;
import com.ev.hr.enums.InterviewStateDict;
import com.ev.hr.enums.ResumeStateDict;
import com.ev.hr.service.InterviewRecordService;
import com.ev.hr.vo.*;
import com.ev.system.domain.UserDO;
import com.ev.system.service.UserService;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;


@Service
public class InterviewRecordServiceImpl implements InterviewRecordService {
    @Autowired
    private InterviewRecordDao interviewRecordDao;
    @Autowired
    private InterviewRecordDetailDao interviewRecordDetailDao;
    @Autowired
    private CandidateInfoDao candidateInfoDao;
    @Autowired
    private UserService userService;
    @Autowired
    private NoticeService noticeService;
    @Autowired
    private ContentAssocService contentAssocService;
    @Autowired
    private MessageSourceHandler messageSourceHandler;

    @Override
    public InterviewRecordDO get(Long id) {
        return interviewRecordDao.get(id);
    }

    @Override
    public List<InterviewRecordDO> list(Map<String, Object> map) {
        return interviewRecordDao.list(map);
    }

    @Override
    public int count(Map<String, Object> map) {
        return interviewRecordDao.count(map);
    }

    @Override
    public int save(InterviewRecordDO interviewRecord) {
        return interviewRecordDao.save(interviewRecord);
    }

    @Override
    public int update(InterviewRecordDO interviewRecord) {
        return interviewRecordDao.update(interviewRecord);
    }

    @Override
    public int updateAll(InterviewRecordDO interviewRecord) {
        return interviewRecordDao.updateAll(interviewRecord);
    }

    @Override
    public int remove(Long id) {
        return interviewRecordDao.remove(id);
    }

    @Override
    public int batchRemove(Long[] ids) {
        return interviewRecordDao.batchRemove(ids);
    }

    @Override
    public R saveRecord(InterviewRecordSaveToUpdate saveParam) throws IOException, ParseException {
        Long userId = ShiroUtils.getUserId();
        InterviewRecordDO interviewRecordDO = new InterviewRecordDO();
        BeanUtils.copyProperties(saveParam, interviewRecordDO);
        Long id = interviewRecordDO.getId();
        if (id == null) {
            return R.error();
        }
        InterviewRecordDO recordDO = this.get(id);
        interviewRecordDO.setCandidateId(recordDO.getCandidateId());
        Long interviewResults = interviewRecordDO.getInterviewResults();
        if (interviewResults != null || interviewRecordDO.getRemarks() != null) {
            if (Objects.equals(interviewResults, recordDO.getInterviewResults())) {
                return R.ok();
            }
            if (!Objects.equals(userId, recordDO.getCreateBy())) {
                return R.error(messageSourceHandler.getMessage("hr.interview.nonCreateBy", null));
            }
        }
        // 获取该面试安排下所有的面试记录
        Map<String, Object> param = Maps.newHashMap();
        param.put("recordId", id);
        List<InterviewRecordDetailDO> oldRecordDetail = interviewRecordDetailDao.list(param);

        List<InterviewRecordDetailDO> newRecordDetail = saveParam.getDetail();

        // 发送消息
        JSONObject contentDetail = new JSONObject();
        contentDetail.put("id", id);
        // 前端路由
        contentDetail.put("url", "/interviewManagement/interviewManagement_addRecord?id=" + interviewRecordDO.getCandidateId() + "&" + "interviewId=" + id);

        if (newRecordDetail.size() > 0) {
            newRecordDetail.sort(Comparator.comparing(InterviewRecordDetailDO::getInterviewStage));
            assert userId != null;
            // 验证明细项中是否都能由当前登陆人填写
            long errorCount = newRecordDetail
                    .stream()
                    .filter(e -> {
                        String interviewers = e.getInterviewer();
                        List<String> interviewer = Arrays.asList(interviewers.split(","));
                        return interviewer.size() > 0 && !interviewer.contains(userId.toString());
                    })
                    .count();
            if (errorCount > 0) {
                return R.error(messageSourceHandler.getMessage("hr.interview.recordError", null));
            }

            // 获取本次面试安排的状态

            Long interviewStage = recordDO.getInterviewStage();
            // 本次需要修改的记录
            List<Long> nowIdList = newRecordDetail
                    .stream()
                    .map(InterviewRecordDetailDO::getId)
                    .collect(Collectors.toList());
            // 若本次修改并未涉及到本该进行的阶段则提示错误消息
            if (interviewStage != null && !nowIdList.contains(interviewStage)) {
                return R.error(messageSourceHandler.getMessage("hr.interview.nonArrived", null));
            }

            oldRecordDetail.sort(Comparator.comparing(InterviewRecordDetailDO::getId));
            newRecordDetail.sort(Comparator.comparing(InterviewRecordDetailDO::getId));

//                int size = oldRecordDetail.size();
            // 获取本次面试记录最后一个阶段
            InterviewRecordDetailDO interviewRecordDetailDO = newRecordDetail.get(newRecordDetail.size() - 1);
            Long nowInterviewStage = interviewRecordDetailDO.getId();
            int size = oldRecordDetail.size();
            for (int i = 0; i < size; i++) {
                InterviewRecordDetailDO last = oldRecordDetail.get(i);
                if (Objects.equals(nowInterviewStage, last.getId())) {
                    if (i == size - 1 && last.getInterviewResults() == null) {
                        interviewRecordDO.setInterviewStage(0L);

                        // 若是最后一个流程 通知HR
                        Long createBy = recordDO.getCreateBy();
                        List<Long> usersToLong = Lists.newArrayList();
                        usersToLong.add(createBy);
                        String content = interviewRecordDO.getCandidateName() + "最后一轮面试已结束，请及时关注！";
                        // 6： @我的面试日程 的消息类型
                        noticeService.saveAndSendSocket("@我的面试日程", content, id, contentDetail.toString(), 6L, userId, usersToLong);
                        break;
                    }
                }
            }
            interviewRecordDetailDao.batchUpdate(newRecordDetail);
        }

        String interviewResultsName = "";
        if (interviewResults != null) {
            // 消息通知所有面试官
            if (Objects.equals(InterviewStateDict.NOT_PASS.getId(), interviewResults)) {
                interviewResultsName = InterviewStateDict.NOT_PASS.getName();
            }
            if (Objects.equals(InterviewStateDict.PASS.getId(), interviewResults)) {
                interviewResultsName = InterviewStateDict.PASS.getName();
            }
            String interviewers = oldRecordDetail
                    .stream()
                    .map(InterviewRecordDetailDO::getInterviewer)
                    .collect(Collectors.joining(","));

            // 消息通知所有面试官

            List<String> toUsers = Lists.newArrayList(Arrays.asList(interviewers.split(",")));
            toUsers.removeIf(String::isEmpty);
            List<Long> usersToLong = toUsers.stream()
                    .map(Long::parseLong)
                    .distinct()
                    .collect(Collectors.toList());
            String content = interviewRecordDO.getCandidateName() + "面试" + interviewResultsName + "！";
            // 6： @我的面试日程 的消息类型
            noticeService.saveAndSendSocket("@我的面试日程", content, id, contentDetail.toString(), 6L, userId, usersToLong);

            // 面试结束修改简历状态为面试结果
            CandidateInfoDO candidateInfoDO = new CandidateInfoDO();
            candidateInfoDO.setInterviewState(interviewResults);
            candidateInfoDO.setId(interviewRecordDO.getCandidateId());
            candidateInfoDao.update(candidateInfoDO);
        }

        interviewRecordDao.update(interviewRecordDO);
        Map<String, Object> result = Maps.newHashMap();
        result.put("id", id);
        return R.ok(result);
    }

    @Override
    public R saveSchedule(InterviewScheduleSaveToUpdate saveParam) throws IOException, ParseException {
        Long userId = ShiroUtils.getUserId();
        InterviewRecordDO interviewRecordDO = new InterviewRecordDO();
        BeanUtils.copyProperties(saveParam, interviewRecordDO);
        Long id = interviewRecordDO.getId();
        boolean isInsert = saveParam.getId() == null;
        if (isInsert) {
            interviewRecordDao.save(interviewRecordDO);
            id = interviewRecordDO.getId();
        }

        // 获取该面试安排下所有的面试记录
        Map<String, Object> param = Maps.newHashMap();
        param.put("recordId", id);
        List<InterviewRecordDetailDO> oldRecordDetail = interviewRecordDetailDao.list(param);

        List<InterviewRecordDetailDO> newRecordDetail = saveParam.getDetail();
        if (newRecordDetail.size() == 0) {
            return R.error();
        }
        // 发送消息
        JSONObject contentDetail = new JSONObject();
        contentDetail.put("id", id);
        // 前端路由
        contentDetail.put("url", "/interviewManagement/interviewManagement_addRecord?id=" + interviewRecordDO.getCandidateId() + "&" + "interviewId=" + id);


        newRecordDetail.removeIf(e -> e.getInterviewResults() != null);
        boolean isEmptyRecord = newRecordDetail.size() == 0;
        // 若删除了所有项目
        InterviewRecordDetailDO firstRecord = isEmptyRecord ? (new InterviewRecordDetailDO()) : newRecordDetail.get(0);
        String firstInterviewStage = firstRecord.getInterviewStage();
        String firstInterviewer = firstRecord.getInterviewer();
        Date firstInterviewDate = firstRecord.getInterviewDate();

        if (isInsert) {
            final Long finalId = id;
            newRecordDetail.forEach(e -> e.setRecordId(finalId));

            // 消息通知第一批面试官
            List<String> toUsers = Lists.newArrayList(Arrays.asList(firstInterviewer.split(",")));
            toUsers.removeIf(String::isEmpty);
            List<Long> usersToLong = toUsers.stream()
                    .map(Long::parseLong)
                    .collect(Collectors.toList());
            // 6： @我的面试日程 的消息类型
            String content = "时间:" + DateFormatUtil.getFormateDate(firstInterviewDate) + "," + interviewRecordDO.getCandidateName() + "需要" + firstInterviewStage + "面试，请及时关注！";
            noticeService.saveAndSendSocket("@我的面试日程", content, id, contentDetail.toString(), 6L, ShiroUtils.getUserId(), usersToLong);

            interviewRecordDetailDao.batchSave(newRecordDetail);

            // 修改面试状态为面试记录的第一个状态d的记录ID
            interviewRecordDO.setInterviewStage(newRecordDetail.get(0).getId());
            this.update(interviewRecordDO);

            // 修改简历状态为面试中
            CandidateInfoDO candidateInfoDO = new CandidateInfoDO();
            candidateInfoDO.setInterviewState(InterviewStateDict.INTERVIEW.getId());
            candidateInfoDO.setId(saveParam.getCandidateId());
            candidateInfoDao.update(candidateInfoDO);
        }

        // 若是新增则发消息给第一批面试官 并新增面试记录
        if (!isInsert) {
            // 获取本次面试安排的状态
            InterviewRecordDO recordDO = this.get(id);
            Long interviewStage = recordDO.getInterviewStage();
            if (!Objects.equals(userId, recordDO.getCreateBy())) {
                return R.error(messageSourceHandler.getMessage("hr.interview.nonCreateBy", null));
            }
            if (recordDO.getInterviewResults() != null) {
                return R.error(messageSourceHandler.getMessage("hr.interview.isComplete.nonInsert", null));
            }
            List<Long> deleteIds = saveParam.getDetailIds();
            boolean isDelete = deleteIds != null && deleteIds.size() > 0;
            // 找出已填写过的
            List<Long> filledRecordIdList = oldRecordDetail
                    .stream()
                    .filter(e -> e.getInterviewResults() != null)
                    .map(InterviewRecordDetailDO::getId)
                    .collect(Collectors.toList());

            if (filledRecordIdList.size() > 0) {
                Long finalInterviewStage1 = filledRecordIdList.get(0);
                newRecordDetail.removeIf(e -> e.getId() != null && e.getId() <= finalInterviewStage1);
                List<InterviewRecordDetailDO> errorList = newRecordDetail
                        .stream()
                        .filter(e -> e.getId() != null && filledRecordIdList.contains(e.getId()))
                        .collect(Collectors.toList());
                if (errorList.size() > 0) {
                    String errorStage = errorList
                            .stream()
                            .map(InterviewRecordDetailDO::getInterviewStage)
                            .collect(Collectors.joining(","));
                    String[] args = {errorStage};
                    return R.error(messageSourceHandler.getMessage("hr.interview.isComplete", args));

                }
            }
            if (isDelete) {
                // 若是删除项目有被面试过的禁止修改
                List<Long> errorDeleteList = deleteIds.stream()
                        .filter(filledRecordIdList::contains)
                        .collect(Collectors.toList());
                if (errorDeleteList.size() > 0) {
                    String errorStage = oldRecordDetail
                            .stream()
                            .filter(e -> errorDeleteList.contains(e.getId()))
                            .map(InterviewRecordDetailDO::getInterviewStage)
                            .collect(Collectors.joining(","));

                    String[] args = {errorStage};
                    return R.error(messageSourceHandler.getMessage("hr.interview.isComplete", args));
                }
            }
            for (InterviewRecordDetailDO interviewRecordDetailDO : newRecordDetail) {
                if (interviewRecordDetailDO.getId() == null) {
                    interviewRecordDetailDO.setRecordId(id);
                    interviewRecordDetailDao.save(interviewRecordDetailDO);
                } else {
                    interviewRecordDetailDao.update(interviewRecordDetailDO);
                }
            }
            if (!isEmptyRecord && interviewStage == 0L) {
                // 消息通知下一个阶段的面试官

                List<String> toUsersNow = Lists.newArrayList(Arrays.asList(firstInterviewer.split(",")));
                toUsersNow.removeIf(String::isEmpty);
                List<Long> toUsersNowLong = toUsersNow.stream()
                        .map(Long::parseLong)
                        .collect(Collectors.toList());
                String content = "时间:" + DateFormatUtil.getFormateDate(firstInterviewDate) + "," + interviewRecordDO.getCandidateName() + "的面试请及时关注！";
                // 6： @我的面试日程 的消息类型
                noticeService.saveAndSendSocket("@我的面试日程", content, id, contentDetail.toString(), 6L, ShiroUtils.getUserId(), toUsersNowLong);
                interviewStage = firstRecord.getId();
            }
            if (isDelete) {
                // 若是删除了本该进行的阶段或是 最后一个阶段结束后新增的阶段，则发消息通知
                if (deleteIds.contains(interviewStage)) {
                    InterviewRecordDetailDO recordDetailDO = interviewRecordDetailDao.get(interviewStage);
                    String interviewers = recordDetailDO.getInterviewer();

                    // 消息通知删除的面试官
                    List<String> toUsers = Lists.newArrayList(Arrays.asList(interviewers.split(",")));
                    toUsers.removeIf(String::isEmpty);
                    List<Long> usersToLong = toUsers.stream()
                            .map(Long::parseLong)
                            .collect(Collectors.toList());
                    String content = "时间:" + DateFormatUtil.getFormateDate(recordDetailDO.getInterviewDate()) + "," + interviewRecordDO.getCandidateName() + "的面试已取消！";
                    // 6： @我的面试日程 的消息类型
                    noticeService.saveAndSendSocket("@我的面试日程", content, id, contentDetail.toString(), 6L, ShiroUtils.getUserId(), usersToLong);

                    // 消息通知下一个阶段的面试官
                    // 发送消息
                    if (!isEmptyRecord) {
                        List<String> toUsersNow = Lists.newArrayList(Arrays.asList(firstInterviewer.split(",")));
                        toUsersNow.removeIf(String::isEmpty);
                        List<Long> toUsersNowLong = toUsersNow.stream()
                                .map(Long::parseLong)
                                .collect(Collectors.toList());
                        content = "时间:" + DateFormatUtil.getFormateDate(firstInterviewDate) + "," + interviewRecordDO.getCandidateName() + "的面试请及时关注！";
                        // 6： @我的面试日程 的消息类型
                        noticeService.saveAndSendSocket("@我的面试日程", content, id, contentDetail.toString(), 6L, ShiroUtils.getUserId(), toUsersNowLong);
                        interviewStage = firstRecord.getId();
                    }
                }
                interviewRecordDetailDao.batchRemove(deleteIds.toArray(new Long[0]));
            }

            if (!isEmptyRecord) {
                // 找出当前阶段是否进行了修改
                Long finalInterviewStage = interviewStage;
                List<InterviewRecordDetailDO> newUpdateRecord = newRecordDetail
                        .stream()
                        .filter(e -> Objects.equals(finalInterviewStage, e.getId()))
                        .collect(Collectors.toList());
                List<InterviewRecordDetailDO> oldUpdateRecord = oldRecordDetail
                        .stream()
                        .filter(e -> Objects.equals(finalInterviewStage, e.getId()))
                        .collect(Collectors.toList());

                if (newUpdateRecord.size() > 0 && oldUpdateRecord.size() > 0) {
                    // 若是当前阶段数据有变更则提醒
                    InterviewRecordDetailDO oldR = oldUpdateRecord.get(0);
                    InterviewRecordDetailDO newR = newUpdateRecord.get(0);
                    if (!Objects.equals(oldR.getInterviewer(), newR.getInterviewer())
                            || !Objects.equals(oldR.getInterviewDate(), newR.getInterviewDate())
//                            || !Objects.equals(oldR.getInterviewStage(), newR.getInterviewStage())
                    ) {
                        // 消息通知修改后的的面试官
                        String interviewers = oldR.getInterviewer() + "," + newR.getInterviewer();
                        List<String> toUsers = Lists.newArrayList(Arrays.asList(interviewers.split(",")));
                        toUsers.removeIf(String::isEmpty);
                        List<Long> usersToLong = toUsers.stream()
                                .map(Long::parseLong)
                                .distinct()
                                .collect(Collectors.toList());
                        String content = "时间:" + DateFormatUtil.getFormateDate(newR.getInterviewDate()) + "," + interviewRecordDO.getCandidateName() + "的面试有变更，请及时关注！";
                        // 6： @我的面试日程 的消息类型
                        noticeService.saveAndSendSocket("@我的面试日程", content, id, contentDetail.toString(), 6L, ShiroUtils.getUserId(), usersToLong);
                    }
                }
                recordDO.setInterviewStage(finalInterviewStage);
            } else {
                // 若面试阶段已为空则设置阶段结束
                recordDO.setInterviewStage(0L);
            }

            this.update(recordDO);
        }
        Map<String, Object> result = Maps.newHashMap();
        result.put("id", id);
        return R.ok(result);
    }

    @Override
    public Map<String, Object> getById(Long id) {
        Map<String, Object> interviewRecord = interviewRecordDao.getById(id);
        if (interviewRecord != null) {
            String stage = interviewRecord.get("interviewStage").toString();
            Long userId = ShiroUtils.getUserId();
            // 全部员工
            Map<String, Object> param = Maps.newHashMap();

            List<UserDO> employeeInfoList = userService.list(param);
            Map<Long, String> userMap = employeeInfoList
                    .stream()
                    .collect(Collectors.toMap(UserDO::getUserId, UserDO::getName));

            // 当前登陆人为面试日程创建人时可以修改表头信息
            Long createBy = Long.parseLong(interviewRecord.get("createBy").toString());
            interviewRecord.put("canModify", Objects.equals(userId, createBy) && StringUtils.isEmpty(interviewRecord.getOrDefault("interviewResults", "").toString()));
            param.put("recordId", id);
            List<Map<String, Object>> recordDetailList = interviewRecordDetailDao.listForMap(param);
            recordDetailList.sort(Comparator.comparing(e -> Long.parseLong(e.get("id").toString())));

            List<Map<String, Object>> userList;
            Map<String, Object> userMaps;
            boolean canModify = false;
            for (Map<String, Object> recordDetailMap : recordDetailList) {
                userList = Lists.newArrayList();
                String interviewers = recordDetailMap.get("interviewer").toString();
                List<String> interviewer = Lists.newArrayList(interviewers.split(","));
                interviewer.removeIf(String::isEmpty);
                assert userId != null;
                // 当前登陆人为面试官时可以修改对应的面试记录
                if (canModify) {
                    canModify = false;
                } else {
                    canModify = interviewer.contains(userId.toString()) && Objects.equals(stage, recordDetailMap.get("id").toString());
                }
                recordDetailMap.put("canModify", canModify);
                // 是否能进行操作
                recordDetailMap.put("canOperate", recordDetailMap.containsKey("interviewResults") || !Objects.equals(userId, createBy));

                // 前端需要封装的参数
                for (String s : interviewer) {
                    userMaps = Maps.newHashMap();
                    long interviewerId = Long.parseLong(s);
                    userMaps.put("id", interviewerId);
                    userMaps.put("name", userMap.get(interviewerId));
                    userList.add(userMaps);
                }
                recordDetailMap.put("interviewerList", userList);

                interviewer.replaceAll(e -> userMap.get(Long.parseLong(e)));
                interviewers = StringUtils.join(interviewer.toArray(), ",");
                recordDetailMap.put("interviewerName", interviewers);

                // 本阶段
                recordDetailMap.put("isNowStage", Objects.equals(stage, recordDetailMap.get("id").toString()));

            }
            // 获取附件
            Map<String, Object> params = Maps.newHashMap();
            params.put("assocId", interviewRecord.getOrDefault("candidateId", 0));
            params.put("assocType", ConstantForHr.RESUME_FILE);
            List<ContentAssocDO> resumeFile = contentAssocService.list(params);
            interviewRecord.put("resumeFile", resumeFile);


            Map<String, Object> result = Maps.newHashMap();
            result.put("headInfo", interviewRecord);
            result.put("bodyInfo", recordDetailList);
            return R.ok(result);
        }
        return R.error();
    }

    @Override
    public Map<String, Object> pageList(InterviewRecordPageParam pageParam) {
        List<Long> interviewStateList = Lists.newArrayList();
        interviewStateList.add(InterviewStateDict.NOT_START.getId());
        interviewStateList.add(InterviewStateDict.NOT_PASS.getId());
        interviewStateList.add(InterviewStateDict.PASS.getId());
        interviewStateList.add(InterviewStateDict.INTERVIEW.getId());
        pageParam.setInterviewStateList(interviewStateList);
        pageParam.setAdvertisePositionName(StringUtils.sqlLike(pageParam.getAdvertisePositionName()));
        pageParam.setCandidateName(StringUtils.sqlLike(pageParam.getCandidateName()));
        return getPageList(pageParam);
    }

    @Override
    public Map<String, Object> hireList(InterviewRecordPageParam pageParam) {
        List<Long> interviewStateList = Lists.newArrayList();
        interviewStateList.add(InterviewStateDict.WAIT_OFFER.getId());
        interviewStateList.add(InterviewStateDict.SEND_OFFER.getId());
        interviewStateList.add(InterviewStateDict.WORKING.getId());
        pageParam.setInterviewStateList(interviewStateList);

        return getPageList(pageParam);
    }

    private Map<String, Object> getPageList(InterviewRecordPageParam pageParam) {
        Map<String, Object> result = Maps.newHashMap();
        pageParam.setCandidateName(StringUtils.sqlLike(pageParam.getCandidateName()));
        pageParam.setAdvertisePositionName(StringUtils.sqlLike(pageParam.getAdvertisePositionName()));
        List<Map<String, Object>> data = interviewRecordDao.pageList(pageParam);
        if (data.size() > 0) {
            List<Object> idList = data
                    .stream()
                    .map(e -> e.get("candidateId"))
                    .collect(Collectors.toList());
            Map<String, Object> param = Maps.newHashMap();
            param.put("assocIds", idList);
            param.put("assocType", ConstantForHr.RESUME_FILE);
            List<ContentAssocDO> resumeFileList = contentAssocService.list(param);
            Map<Long, List<ContentAssocDO>> collect = resumeFileList
                    .stream()
                    .collect(Collectors.groupingBy(ContentAssocDO::getAssocId));
            for (Map<String, Object> datum : data) {
                Long id = Long.parseLong(datum.get("candidateId").toString());
                if (collect.containsKey(id)) {
                    datum.put("isEmptyFile", false);
                    datum.put("fileList", collect.get(id));
                } else {
                    datum.put("isEmptyFile", true);
                }
            }

            int total = interviewRecordDao.pageCount(pageParam);
            result.put("data", new DsResultResponse(pageParam.getPageno(), pageParam.getPagesize(), total, data));

        }
        return result;
    }


    @Override
    public R updateResumeState(ResumeStateVO resumeStateVO) {
        List<Long> candidateIds = resumeStateVO.getCandidateIds();
        if (candidateIds != null && candidateIds.size() > 0) {
            Integer updateType = resumeStateVO.getUpdateType();
            if (updateType == null) {
                updateType = 0;
            }
            Long interviewState = null;
            Long resumeState = null;
            Integer delFlag = null;
            // "录用清单:0，转重点人才库:1，转黑名单:2，发送offer:3，取消录用:4，入职:5,转其他:6"
            switch (updateType) {
                case 0:
                    interviewState = InterviewStateDict.WAIT_OFFER.getId();
                    for (Long candidateId : candidateIds) {
                        InterviewRecordDO byCandidateId = interviewRecordDao.getByCandidateId(candidateId);
                        if (byCandidateId==null
                                ||byCandidateId.getInterviewResults()==null
                                ||Objects.equals(byCandidateId.getInterviewResults(),InterviewStateDict.NOT_PASS.getId())){
                            String[]args = {byCandidateId==null?"":byCandidateId.getCandidateName()};
                            return R.error(messageSourceHandler.getMessage("hr.interview.nonComplete", args));
                        }
                    }

                    break;
                case 1:
                    resumeState = ResumeStateDict.PREFERRED_TALENT.getId();
                    interviewState = InterviewStateDict.CANCEL_HIRE.getId();
                    break;
                case 2:
                    resumeState = ResumeStateDict.BLACKLIST.getId();
                    interviewState = InterviewStateDict.CANCEL_HIRE.getId();
                    break;
                case 3:
                    interviewState = InterviewStateDict.SEND_OFFER.getId();
                    break;
//                case 4:
//                    interviewState = InterviewStateDict.CANCEL_HIRE.getId();
//                    resumeState = ResumeStateDict.TALENT_POOL.getId();
//                    break;
                case 5:
                    // 若是已入职简历则逻辑删除
                    delFlag = 1;
                    interviewState = InterviewStateDict.WORKING.getId();
                    break;
                case 6:
                    interviewState = InterviewStateDict.CANCEL_HIRE.getId();
                    resumeState = ResumeStateDict.TALENT_POOL.getId();
                    break;
                default:
                    break;
            }

            // 修改简历状态
            CandidateInfoDO candidateInfoDO;
            List<CandidateInfoDO> candidateInfoList = Lists.newArrayList();
            for (Long id : candidateIds) {
                candidateInfoDO = new CandidateInfoDO();
                candidateInfoDO.setId(id);
                candidateInfoDO.setInterviewState(interviewState);
                candidateInfoDO.setResumeState(resumeState);
                candidateInfoDO.setDelFlag(delFlag);
                candidateInfoList.add(candidateInfoDO);
            }
            candidateInfoDao.batchUpdate(candidateInfoList);
            return R.ok();
        }
        return R.error();
    }

    @Override
    public R nextStep(InterviewRecordSaveToUpdate saveParam) throws IOException, ParseException {
        Long id = saveParam.getId();
        // 获取该面试安排下所有的面试记录
        Map<String, Object> param = Maps.newHashMap();
        param.put("recordId", id);
        List<InterviewRecordDetailDO> oldRecordDetail = interviewRecordDetailDao.list(param);
        oldRecordDetail.sort(Comparator.comparing(InterviewRecordDetailDO::getId));
        InterviewRecordDO interviewRecordDO = this.get(id);
        Long interviewStage = interviewRecordDO.getInterviewStage();
        int size = oldRecordDetail.size();
        for (int i = 0; i < size; i++) {
            if (Objects.equals(oldRecordDetail.get(i).getId(), interviewStage)) {
                if (i == size - 1) {
                    // 若是最后一个流程则不会进行通知
                    return R.error(messageSourceHandler.getMessage("hr.interview.isEnd", null));
                }
                InterviewRecordDetailDO interviewRecordDetailDO = oldRecordDetail.get(i + 1);
                // 若是中间流程
                // 消息通知第下一批面试官
                // 发送消息
                JSONObject contentDetail = new JSONObject();
                contentDetail.put("id", id);
                // 前端路由
                contentDetail.put("url", "/interviewManagement/interviewManagement_addRecord?id=" + interviewRecordDO.getCandidateId() + "&" + "interviewId=" + id);
                List<String> toUsers = Lists.newArrayList(Arrays.asList(oldRecordDetail.get(i + 1).getInterviewer().split(",")));
                toUsers.removeIf(String::isEmpty);
                List<Long> usersToLong = toUsers.stream()
                        .map(Long::parseLong)
                        .collect(Collectors.toList());
                String content = "时间:" + DateFormatUtil.getFormateDate(interviewRecordDetailDO.getInterviewDate()) + "," + interviewRecordDO.getCandidateName() + "需要面试，请及时关注！";
                // 6： @我的面试日程 的消息类型
                noticeService.saveAndSendSocket("@我的面试日程", content, id, contentDetail.toString(), 6L, ShiroUtils.getUserId(), usersToLong);

                // 将面试进行到下一阶段
                interviewRecordDO.setInterviewStage(interviewRecordDetailDO.getId());
                break;
            }
        }

        InterviewRecordDetailDO interviewRecordDetailDO = interviewRecordDetailDao.get(interviewStage);
        if (interviewRecordDetailDO.getInterviewResults() == null) {
            // 若是不填结果直接进入下一轮则是默认通过
            interviewRecordDetailDO.setInterviewResults(InterviewStateDict.PASS.getId());
            interviewRecordDetailDao.update(interviewRecordDetailDO);
        }
        this.update(interviewRecordDO);

        List<InterviewRecordDetailDO> detail = saveParam.getDetail();
        detail.removeIf(e -> !Objects.equals(e.getId(), interviewStage));
        if (detail.size() > 0) {
            InterviewRecordDetailDO detailRecord = detail.get(0);
            interviewRecordDetailDao.update(detailRecord);
        }
        
        return R.ok();
    }

    @Override
    public R checkNextStep(InterviewRecordSaveToUpdate saveParam) {
        Long id = saveParam.getId();
        Long userId = ShiroUtils.getUserId();
        // 获取该面试安排下所有的面试记录
        Map<String, Object> param = Maps.newHashMap();
        param.put("recordId", id);
        List<InterviewRecordDetailDO> oldRecordDetail = interviewRecordDetailDao.list(param);
        oldRecordDetail.sort(Comparator.comparing(InterviewRecordDetailDO::getId));
        InterviewRecordDO interviewRecordDO = this.get(id);
        Long interviewStage = interviewRecordDO.getInterviewStage();
        if (interviewStage == 0L) {
            return R.error(messageSourceHandler.getMessage("hr.interview.isEnd", null));
        }
        int size = oldRecordDetail.size();
        for (int i = 0; i < size; i++) {
            if (Objects.equals(oldRecordDetail.get(i).getId(), interviewStage)) {
                if (i == size - 1) {
                    // 若是最后一个流程则不会进行通知
                    return R.error(messageSourceHandler.getMessage("hr.interview.isEnd", null));
                }
                if (Objects.equals(interviewRecordDO.getCreateBy(), userId)) {
                    return R.ok();
                }

                // 找出当前阶段的面试记录且应该填写过才可进入下一轮
                List<InterviewRecordDetailDO> collect = oldRecordDetail.stream()
                        .filter(e -> Objects.equals(interviewStage, e.getId()))
                        .collect(Collectors.toList());
                InterviewRecordDetailDO interviewRecordDetailDO = collect.get(0);
                if (interviewRecordDetailDO.getInterviewResults() == null) {
                    return R.error(messageSourceHandler.getMessage("hr.interview.nonWrite", null));
                }
                List<String> interviewer = Arrays.asList(interviewRecordDetailDO.getInterviewer().split(","));
                assert userId != null;
                if (!interviewer.contains(userId.toString())) {
                    return R.error(messageSourceHandler.getMessage("hr.interview.errorOperate", null));
                }
                break;
            }
        }
        return R.ok();
    }

    @Override
    public Map<String, Object> pageListForMyself(InterviewRecordDetailPageParam pageParam) {
        Long userId = ShiroUtils.getUserId();
        Map<String, Object> result = Maps.newHashMap();
        if (userId == null) {
            return result;
        }
        String userIdLike = "%," + userId + ",%";
        String advertisePosition = pageParam.getAdvertisePositionName();
        if (advertisePosition != null) {
            pageParam.setAdvertisePositionName("%" + advertisePosition + "%");
        }

        pageParam.setUserId(userIdLike);
        List<Map<String, Object>> data = interviewRecordDetailDao.pageList(pageParam);
        if (data.size() > 0) {
            int total = interviewRecordDetailDao.pageCount(pageParam);
            result.put("data", new DsResultResponse(pageParam.getPageno(), pageParam.getPagesize(), total, data));
        }
        return result;

    }

}
